package com.racetime.util;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.time.Instant;
import java.util.LinkedList;
import java.util.List;
import java.util.ResourceBundle;
import java.util.logging.Logger;

/**
 * @author : Ice'Clean
 * @date : 2021-05-13
 *
 *
 */
public class MyConnectionPoolImpl implements MyConnectionPool {

    Logger poolLogger = MyLogger.getLogger("pool");
    private static final String RESOURCE_NAME = "racetime";
    private static final String URL;
    private static final String USER;
    private static final String PASSWORD;

    /**
     * 数据库连接的存放池
     */
    private final List<Connection> connPool = new LinkedList<>();

    /**
     * 最大的空闲连接数量（默认10）
     */
    private int maxFreeConnections = 10;

    /**
     * 存放最后一次的使用时间，如果超过 8 个小时，则更新数据库连接
     */
    private long lastTime;

    /**
     * 数据库连接超时时间，设置为 8 个小时（以秒为单位）
     */
    private static final int OVER_TIME = 8 * 60 * 60;

    // 在静态代码块中注册驱动
    static
    {
        ResourceBundle bundle = ResourceBundle.getBundle(RESOURCE_NAME);
        URL = bundle.getString("url");
        USER = bundle.getString("user");
        PASSWORD = bundle.getString("password");

        try {
            Class.forName(bundle.getString("driver"));
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    @Override
    public Connection getConnection() throws SQLException {
        // 比较时间，若超时则替换连接池连接
        if (Instant.now().getEpochSecond() - lastTime > OVER_TIME) {
            poolLogger.info("连接超时了，重新获取 10 个连接");
            connPool.clear();
            initPool();
        }

        // 如果连接池为空，新建连接
        if (connPool.isEmpty()) {
            poolLogger.info("连接池空了，再新建 10 个连接");
            initPool();
        }

        // 给出一个有效数据库连接
        poolLogger.info("给出了一个连接，目前剩余连接数：" + (connPool.size()-1) +
                " （该批连接持续服务时间："+ (Instant.now().getEpochSecond() - lastTime) +" / "+ OVER_TIME +" s）");
        return connPool.remove(0);
    }


    @Override
    public void initPool() throws SQLException {
        // 获取数据库连接并放入数据库连接池中
        for (int i = 0; i < maxFreeConnections; i++) {
            connPool.add(DriverManager.getConnection(URL, USER, PASSWORD));
        }

        // 更新此次的连接时间
        lastTime = Instant.now().getEpochSecond();
        poolLogger.info("新开了 10 个数据库连接");
    }

    @Override
    public void closeConnection(Connection conn) throws SQLException {
        // 如果连接池中的连接数量小于最大数量，且该连接可用
        if (!conn.isClosed()) {
            if (connPool.size() < maxFreeConnections) {
                //则将空闲连接放进去
                connPool.add(conn);
                poolLogger.info("将 1 个连接回收了，目前剩余连接数：" + connPool.size());
            } else {
                // 否则将连接关闭
                poolLogger.info("该连接已失效或连接池已满，不放入连接池，目前剩余连接数 ：" + connPool.size());
                conn.close();
            }
        }
    }

    @Override
    public void setMaxFreeConnections(int maxFreeConnections) {
        this.maxFreeConnections = maxFreeConnections;
    }

    @Override
    public int getMaxFreeConnections() {
        return maxFreeConnections;
    }
}
